// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CLOUDAPPENGINE_CAESOCKET_H
#define CLOUDAPPENGINE_CAESOCKET_H

#include <pthread.h>
#include <string>
#include "../cae_common/CaeDefine.h"

constexpr int SOCKET_STATUS_NORMAL = 1;
constexpr int SOCKET_STATUS_ERROR = -1;

class CaeEventNotice {
public:
    CaeEventNotice() {}

    virtual ~CaeEventNotice() {}

    virtual void Notice(void *pTcpSocket) = 0;
};


class CaeServerService {
public:
    CaeServerService() {}

    virtual int Callback(void *tcpSocket) = 0;

    virtual ~CaeServerService() {}

    std::string ClientType2string(enum ClientType type)
    {
        switch (type) {
            ENUM_CHIP_TYPE_CASE(APP_TCP)
            ENUM_CHIP_TYPE_CASE(APP_TLS)
            ENUM_CHIP_TYPE_CASE(H5_WS)
            ENUM_CHIP_TYPE_CASE(H5_WSS)
            default:
                return "CLIENT_TYPE";
        }
    };
};


class CaeSocket {
public:
    virtual ~CaeSocket()
    {
        if (m_eventNotice != nullptr) {
            delete m_eventNotice;
            m_eventNotice = nullptr;
        }
    };

    virtual int Send(void *pPkt, size_t size) = 0;
    virtual int Recv(void *pPkt, size_t size) = 0;

    virtual void EventNotice();

    virtual void SetEventNotice(CaeEventNotice *localPEventNotice);

    virtual void SetFd(int fd);

    virtual int GetFd();

    virtual void SetStatus(int status);

    virtual int GetStatus();

    virtual void SetSocketOption(uint32_t localSocketOption);

    virtual int GetSocketOption();

    virtual void SetAddress(uint32_t localRemoteIp, uint16_t localRemotePort, uint32_t localLocalIp,
        uint16_t localLocalPort);

    virtual void GetAddress(uint32_t *pRemoteIp, uint16_t *pRemotePort, uint32_t *pLocalIp, uint16_t *pLocalPort);

    virtual void CloseSocket() = 0;

    virtual void SetSocketTimeout(long sec, long usec) {}

    void SetRemoteIpStr(const std::string &mRemoteIpStr);

    void SetRemotePortStr(const std::string &portStr);

    std::string GetConnectionId();

    std::string GetRemoteIpStr() const;

    std::string GetRemotePortStr() const;

    void SetServerType(ServerType mServerType);

    ServerType GetServerType() const;

protected:
    int m_fd;
    int m_status;
    uint32_t m_localIp;
    uint32_t m_remoteIp;
    uint16_t m_localPort;
    uint16_t m_remotePort;
    uint32_t m_socketOption;
    CaeEventNotice *m_eventNotice;
    pthread_mutex_t m_socketMutex;

    std::string m_remoteIpStr;
    std::string m_remotePortStr;
    ServerType m_serverType;
};

#endif // CLOUDAPPENGINE_CAESOCKET_H
